#include <iostream>
#include <arpa/inet.h>
#include <cstring>
#include <unistd.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <functional>

#define MAX_EVENTS 1024
#define BUFFER_SIZE 1024

using func_t = std::function<std::string(const std::string &)>;

class EpollServer
{
private:
    int _port;
    int _listenSockFd;
    int _epollFd;
    func_t _func;

public:
    EpollServer(int port, func_t func)
        : _port(port), _listenSockFd(-1), _epollFd(-1), _func(func)
    {
    }
    ~EpollServer()
    {
        if (_listenSockFd != -1)
            close(_listenSockFd);
        if (_epollFd != -1)
            close(_epollFd);
    }
    bool InitServer()
    {
        _listenSockFd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listenSockFd < 0)
        {
            perror("TCP socket failed");
            return false;
        }
        struct sockaddr_in servaddr;
        socklen_t len = sizeof(servaddr);
        memset(&servaddr, 0, len);
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(_port);
        servaddr.sin_addr.s_addr = INADDR_ANY;

        if (bind(_listenSockFd, (struct sockaddr *)&servaddr, len) < 0)
        {
            perror("TCP bind failed");
            close(_listenSockFd);
            return false;
        }
        if (listen(_listenSockFd, 10) < 0)
        {
            perror("TCP listen failed");
            close(_listenSockFd);
            return false;
        }
        // 1.创建epoll实例
        _epollFd = epoll_create1(0);
        if (_epollFd < 0)
        {
            perror("epoll create failed");
            close(_listenSockFd);
            return false;
        }
        // 2.将监听套接字添加到epoll实例
        epoll_event ev{};
        ev.events = EPOLLIN;
        ev.data.fd = _listenSockFd;
        if (epoll_ctl(_epollFd, EPOLL_CTL_ADD, _listenSockFd, &ev) < 0)
        {
            perror("epoll_ctl failed");
            close(_listenSockFd);
            close(_epollFd);
            return false;
        }
        return true;
    }
    void Loop()
    {
        if (_epollFd < 0 || _listenSockFd < 0)
        {
            std::cerr << "Server is not properly initialized!" << std::endl;
            return;
        }
        epoll_event events[MAX_EVENTS];
        while (true)
        {
            // 等待事件触发
            int n = epoll_wait(_epollFd, events, MAX_EVENTS, -1);
            if (n < 0)
            {
                perror("epoll_wait failed");
                break;
            }
            for (int i = 0; i < n; i++)
            {
                if (events[i].data.fd == _listenSockFd)
                {
                    // 处理新连接
                    HandleNewConnection();
                }
                else
                {
                    // 处理客户端数据
                    HandleClient(events[i].data.fd);
                }
            }
        }
    }

private:
    void setNonBlocking(int sockFd)
    {
        int flags = fcntl(sockFd, F_GETFL, 0);
        fcntl(sockFd, F_SETFL, flags | O_NONBLOCK);
    }
    void HandleNewConnection()
    {
        struct sockaddr_in cliaddr;
        socklen_t len = sizeof(cliaddr);
        memset(&cliaddr, 0, len);
        int newFd = accept(_listenSockFd, (struct sockaddr *)&cliaddr, &len);
        if (newFd < 0)
        {
            perror("accept newFd failed");
            return;
        }
        // 将新连接设置为非阻塞
        setNonBlocking(newFd);
        // 添加到epoll模型中
        epoll_event ev{};
        ev.events = EPOLLIN | EPOLLET; // 边沿触发（ET）
        ev.data.fd = newFd;
        if (epoll_ctl(_epollFd, EPOLL_CTL_ADD, newFd, &ev) < 0)
        {
            perror("epoll_ctl failed");
            close(newFd);
            return;
        }
    }
    void HandleClient(int ClientFd)
    {
        char buffer[BUFFER_SIZE]{0};

        int byteReads = read(ClientFd, buffer, sizeof(buffer) - 1);
        if (byteReads <= 0)
        {
            //客户端断开连接或发生错误
            if(byteReads==0)
            {
                //断开连接
                std::cout<<"client disconnected:" <<ClientFd<<std::endl;
            }
            else
            {
                perror("recv failed");
            }
            close(ClientFd);
            epoll_ctl(_epollFd,EPOLL_CTL_DEL,ClientFd,nullptr);
        }
        else
        {
            buffer[byteReads]='\0';
            std::string message(buffer);
            write(ClientFd,_func(message).c_str(),message.length());
        }
    }
};